package com.common.basic.util;

import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

@SuppressWarnings("unchecked")
public class FieldSorter implements Comparator 
{
    private String fieldName;
    private boolean ascending;
    private Class clazz = null;
    private Map<String, Field> mapField;
    
    public FieldSorter(String fieldName, boolean ascending) {
        this.fieldName = fieldName;
        this.ascending = ascending;
        mapField = new HashMap<String, Field>();
    }
    public int compare(Object a, Object b) 
    {
        Object o1 = invoke(a, fieldName);
        Object o2 = invoke(b, fieldName);

        if (o1 instanceof String && ((String)o1).length() == 0) {
            o1 = null;
        }
        if (o2 instanceof String && ((String)o2).length() == 0) {
            o2 = null;
        }

        if (o1 == null && o2 == null) {
            return 0;
        } else if (o1 == null) {
            return -1;
        } else if (o2 == null) {
            return 1;
        } else if (o1 instanceof Comparable) {
            if (ascending) {
                return ((Comparable)o1).compareTo(o2);
            } else {
                return ((Comparable)o2).compareTo(o1);
            }
        } else {
            if (ascending) {
                return o1.toString().compareTo(o2.toString());
            } else {
                return o2.toString().compareTo(o1.toString());
            }
        }
    }
    
    private Object invoke(Object obj, String fieldName)
    {
    	if(obj!=null && fieldName!=null && !"".equals(fieldName))
    	{	
    		try
        	{
        		if(null==clazz)
        		{
        			clazz = obj.getClass();
        			Field[] fields = clazz.getDeclaredFields();
        			mapField.clear();
        			for (int i = 0; i < fields.length; ++i)
        				mapField.put(fields[i].getName(), fields[i]);
        		}
        		if(!clazz.equals(obj.getClass()) || !mapField.containsKey(fieldName)) return null;
        		Field field = mapField.get(fieldName);
        		field.setAccessible(true);
            	return field.get(obj);
        	}catch(Exception ex){}
    	}	
    	return null;
    }
}

